home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 January: Mac OS SDK / Dev.CD Jan 00 SDK1.toast / Development Kits / Mac OS / Multiprocessing 2.0 SDK / Sample Code / SortPictsMP ƒ / Sprocket / Lib / SprocketMain.cp < prev    next >
Encoding:
Text File  |  1999-08-03  |  16.5 KB  |  643 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        SprocketMain.cp
  3.  
  4.     Contains:    The “guts” of a Macintosh application.
  5.  
  6.     Written by: Dave Falkenburg and many other SmartFriends™
  7.  
  8.     Copyright:    © 1993-94 by Dave Falkenburg, all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.      
  12.         <11>    11/16/94    DRF        Added an explicit #include <Traps.h> for latest universal
  13.                                     headers. Also killed off a CFront warning.
  14.         <10>    11/12/94    DRF        Revised QuickDrawGX initialization based on changes made by Jon
  15.                                     Summer. We now use a 'gasz' resource to setup the size of the
  16.                                     graphics heap. Also we are now always TSM aware, not just when
  17.                                     TSMTE is around.
  18.          <9>     11/8/94    DRF        Rolled in LDR’s TSM fixes. Add fonts to the Fonts menu if it
  19.                                     exists. Also, stop openning up the preferences file here.
  20.          <8>     9/27/94    DRF         AppLib.h is now Sprocket.h, also fixed scrap coercion routines
  21.                                      and eliminated HandleUpdate.
  22.          <7>      9/9/94    DRF        Reordered headers and removed redundant #includes.
  23.                                     Conditionalized AOCE support. Also made changes to
  24.                                     TSMEventWrapper to be more like the code in InlineInputSample.
  25.          <6>      9/8/94    DRF        Add HiliteMenu(0) calls after calls to menu handling code
  26.                                     because TSMMenuSelect doesn’t do it. Also reorganized some GX
  27.                                     stuff: allocate and release a graphicsclient (Cam claims this
  28.                                     works on his machine), and turn on all the graphics errors and
  29.                                     notices if qDebug is set.
  30.          <5>      9/7/94    DRF        Rearrange YieldToAnyThread calls to make quitting faster.
  31.          <4>      9/4/94    DRF        Rearrange local variables in HandleMouseDown.
  32.          <3>      9/1/94    DRF        Stop including "MailableWindow.h" here.
  33.          <2>      9/1/94    DRF        More fixes for inline input, but we’re not really done yet.
  34.  */
  35.  
  36. #include "Sprocket.h"
  37.  
  38. #include <limits.h>        //    For LONG_MAX
  39. #include <Multiprocessing.h>
  40. #include <Fonts.h>
  41. #include <Devices.h>
  42. #include <Gestalt.h>
  43. #include <DiskInit.h>
  44. #include <Threads.h>
  45. #include <CodeFragments.h>    //    for kUnresolvedSymbolAddress
  46. #include <Traps.h>
  47. #include <lowmem.h>
  48. #if    qInlineInputAware
  49. #include <TextServices.h>
  50. #include <TSMTE.h>
  51. #endif
  52.  
  53. #if    qUseQuickDrawGX
  54. #include <graphics macintosh.h>
  55. #include <graphics routines.h>
  56. #include <graphics libraries.h>
  57. #include <PrintingManager.h>
  58. #endif
  59.  
  60. #include "StandardMenus.h"
  61. #include "Window.h"
  62. #include "SplashWindow.h"
  63. #include "AppleEventHandling.h"
  64.  
  65. //    Function Prototypes
  66.  
  67. void    main(void);
  68. void    MainEventLoop(void);
  69.  
  70. void    HandleMouseDown(TWindow * topWindowObj, EventRecord * anEvent);
  71. void    HandleClose(WindowPtr aWindow);
  72.  
  73. //    Globals
  74. Boolean             gHasMPLib = true; //Assume they do
  75. Boolean                gDone = false;
  76. Boolean                gMenuBarNeedsUpdate = true;
  77.  
  78. Boolean                gHasColorQuickdraw = false;
  79. Boolean                gHasThreadManager = false;
  80. Boolean                gHasDragManager = false;
  81. Boolean                gHasAppleScript = false;
  82. Boolean                gHasDisplayManager = false;
  83.  
  84. GrafPtr                gWindowManagerPort;
  85. Rect                gDeskRectangle;
  86. RgnHandle            gMouseRegion = nil;
  87.  
  88. short                gPreferencesRsrcRefNum;
  89.  
  90. #if    qAOCEAware
  91. Boolean                gHasAOCE = false;
  92. #endif
  93.  
  94. #if    qInlineInputAware
  95. Boolean                gHasTextServices = false;
  96. Boolean                gHasTSMTE = false;
  97.  
  98. Boolean                TSMEventWrapperForKotoeri(EventRecord *anEvent);
  99.  
  100. #endif
  101.  
  102. #if    qUseQuickDrawGX
  103. Boolean                gHasQuickDrawGX = false;
  104. long                gQuickDrawGXVersion = 0;
  105. long                gQuickDrawGXPrintingVersion = 0;
  106. gxGraphicsClient    gQuickDrawGXClient;
  107. #endif
  108.  
  109. //    Values that can be adjusted by other application code to change
  110. //    the behavior of the MainEventLoop.
  111. //
  112. //    Rules of thumb:
  113. //
  114. //        Increase gXXXRunQuantum (and decrease gXXXSleepQuantum) when:
  115. //            The application has many threads running that need time
  116. //
  117. //        Decrease gXXXRunQuantum when:
  118. //            Sending AppleEvents to other applications
  119. //            Launching other applications
  120. //            Running in the background
  121.  
  122. unsigned long    gForegroundRunQuantum = 0;
  123. unsigned long    gForegroundSleepQuantum = GetCaretTime();
  124. unsigned long    gBackgroundRunQuantum = 0;
  125. unsigned long    gBackgroundSleepQuantum = LONG_MAX;
  126.  
  127. //    Globals used to “tune” the performance of MainEventLoop
  128. //    (assume we’ll be starting in the foreground)
  129.  
  130. static    unsigned long    gRunQuantum = gForegroundRunQuantum;
  131. static    unsigned long    gSleepQuantum = gForegroundSleepQuantum;
  132.  
  133. #ifdef    powerc
  134. #ifndef    __MWERKS__
  135. QDGlobals    qd;
  136. #endif
  137. #endif
  138.  
  139. void
  140. main(void)
  141.     {
  142.     long        feature;
  143.  
  144.     MaxApplZone();
  145.     MoreMasters();
  146.     MoreMasters();
  147.     MoreMasters();
  148.     MoreMasters();
  149.  
  150.     InitGraf(&qd.thePort);    
  151.     InitFonts();
  152.     InitWindows();
  153.     InitMenus();
  154.     TEInit();
  155.     InitDialogs(nil);
  156.  
  157.     if (Gestalt(gestaltQuickdrawFeatures,&feature) == noErr)
  158.         gHasColorQuickdraw = ((feature & (1 << gestaltHasColor)) != 0);
  159.  
  160.     //InitInterruptSafeDebug(nil);
  161.  
  162.     TSplashWindow * splashWindow = new TSplashWindow;
  163.  
  164.     //    Check for and Initialize QuickDraw GX early on to avoid heap fragmentation
  165.     
  166. #if    qUseQuickDrawGX
  167.     //    Check for and initialize QuickDrawGX
  168.     if (Gestalt(gestaltGXVersion, &gQuickDrawGXVersion) == noErr)
  169.         {
  170.         if (Gestalt(gestaltGXPrintingMgrVersion, &gQuickDrawGXPrintingVersion) == noErr)
  171.             {
  172. #ifdef    powerc
  173.             if ((Ptr) GXEnterGraphics != kUnresolvedSymbolAddress)
  174. #endif
  175.             gHasQuickDrawGX = true;
  176.             }
  177.         }
  178.  
  179.     if (gHasQuickDrawGX)
  180.         {
  181.         // Initialize the graphics and printing environments.
  182.         //    For additional details see "IM: QD GX Environment & Utilities."
  183.         
  184.         //    We let QuickDraw GX look for a resource  of type 'gasz' with an ID of 0.
  185.         //    GX uses the first long word of that resource as the graphics heap size.
  186.         //    To determine the memory requirements of your graphics client heap see:
  187.         //    “IM: QD GX Environment & Utilities pp2-8,2-9”
  188.         
  189.         //    NOTE:    If your application does not provide this resource,
  190.         //            QuickDraw GX version 1.0 uses a default size of 600 KB.
  191.  
  192.         gQuickDrawGXClient = GXNewGraphicsClient(nil, kUseGraphicsSizeResource, kAllowGXToExtendGraphicsHeap);
  193.         if (gQuickDrawGXClient)
  194.             {
  195.             //    NOTE:    GXNewGraphicsClient() does not allocate memory to the heap
  196.             //            until GXEnterGraphics()    is called, so go ahead and call it now
  197.             //            while we have a chance to deal with things nicely.
  198.             //
  199.             // NOTE:    GXEnterGraphics() should only fail if there is not enough memory. 
  200.             
  201.             GXEnterGraphics();
  202.  
  203.             if (GXGetGraphicsError(nil) == noErr)
  204.                 {
  205. #if    qUseQuickDrawGXDebugging
  206.                 // If qUseQuickDrawGXDebugging = TRUE, enable on GX Validation and graphics library errors & notices.
  207.  
  208.                 //    NOTES from Jon Summers:
  209.                 //    As you increase the amount of validation, drawing speed will SLOW
  210.                 //    down due to all of the internal checking. Also, if you play with
  211.                 //    settings enough validation seems to become inconsistent
  212.  
  213.                 GXSetValidation(    //    gxInternalValidation    |
  214.                                     //    gxAllObjectValidation    |
  215.                                     //    gxApHeapValidation        |
  216.                                         gxPublicValidation);        // check parameters to public routines
  217.  
  218.                 //    This functionality will only work with the "debugging" version of QuickDraw GX.
  219.                 //    If you don't have the debugging version installed, these functions will not work. 
  220.  
  221.                 SetGraphicsLibraryErrors();
  222.                 SetGraphicsLibraryNotices();    
  223. #endif
  224.                 if (GXInitPrinting() != noErr)        // See IM: QuickDraw GX Printing
  225.                     {
  226.                     //    We couldn’t initialize printing, so clean up pretend GX isn’t around
  227.                     //    ••• For safety’s sake, we’ll probably want to bail here.
  228.                     
  229.                     if (gQuickDrawGXClient)
  230.                         GXDisposeGraphicsClient(gQuickDrawGXClient);
  231.                     gHasQuickDrawGX = false;
  232.                     }
  233.                 }
  234.             }
  235.         }
  236.  
  237.     if (gQuickDrawGXClient)
  238.         InitCommonColors();        // Initialize the CommonColors Library.
  239. #if    qRequireQuickDrawGX
  240.     else
  241.         FatalErrorAlert(kCoreErrorStrings, kNeedsQuickdrawGX);
  242. #endif    //    qRequireQuickDrawGX
  243. #endif    //    qUseQuickDrawGX
  244.  
  245.     if ((Gestalt(gestaltAppleEventsAttr,&feature) == noErr) &&
  246.         (feature & (1 << gestaltAppleEventsPresent)))
  247.         {
  248.         //    Figure out if we need to do AppleEvent recording
  249.         gHasAppleScript = ((feature & (1 << gestaltScriptingSupport)) != 0);
  250.         }
  251.     else
  252.         FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
  253.  
  254. #if    qInlineInputAware
  255.     if ((Gestalt(gestaltTSMgrVersion,&feature) == noErr) && (feature >= 1))
  256.         {
  257.         gHasTextServices = true;
  258.         if (Gestalt(gestaltTSMTEAttr, &feature) == noErr)
  259.             gHasTSMTE = (feature & (1 << gestaltTSMTEPresent));
  260.  
  261.         if (InitTSMAwareApplication() != noErr)
  262.             {
  263.             gHasTextServices = false;
  264.             gHasTSMTE = false;
  265.             }
  266.         }
  267.  
  268. #endif
  269.  
  270.     if (Gestalt(gestaltThreadMgrAttr,&feature) == noErr)
  271.         {
  272. #ifdef    powerc
  273.         //    If running on a PowerPC, make sure that we not only have the
  274.         //    68K Thread Manager, but also the PowerPC shared library, too.
  275.         //    Because of the wonders of weak linking and out of memory errors
  276.         //    we need to also check to make sure that an entrypoint in the library
  277.         //    is there, too. 
  278.         if (long(NewThread) != kUnresolvedCFragSymbolAddress)
  279.             gHasThreadManager = ((feature & ((1 << gestaltThreadMgrPresent) | (1 << gestaltThreadsLibraryPresent))) != 0);
  280. #else
  281.         gHasThreadManager = ((feature & (1 << gestaltThreadMgrPresent)) != 0);
  282. #endif
  283.         }
  284.  
  285. #if    qRequireThreadManager
  286.     if (gHasThreadManager == false)
  287.         FatalErrorAlert(kCoreErrorStrings, kNeedsThreadManager);
  288. #endif
  289.  
  290.     //    Check for and install Drag Manager callbacks
  291.     if (Gestalt(gestaltDragMgrAttr,&feature) == noErr)
  292.         {
  293. #ifdef    powerc
  294.         //    If running on a PowerPC, make sure that we not only have the
  295.         //    68K Drag Manager, but also the PowerPC shared library, too.
  296.         if (long(NewDrag) != kUnresolvedCFragSymbolAddress)
  297.             gHasDragManager = ((feature & ((1 << gestaltDragMgrPresent) | (1 << gestaltPPCDragLibPresent))) != 0);
  298. #else
  299.         gHasDragManager = ((feature & (1 << gestaltDragMgrPresent)) != 0);
  300. #endif
  301.  
  302.         if (gHasDragManager)
  303.             {
  304.             InstallTrackingHandler(NewDragTrackingHandlerProc(CallWindowDragTrackingHandler),(WindowPtr) nil,nil);
  305.             InstallReceiveHandler(NewDragReceiveHandlerProc(CallWindowDragReceiveHandler),(WindowPtr) nil,nil);
  306.             }
  307.         }
  308.  
  309.     //    Check for Display Manager
  310.     if (Gestalt(gestaltDisplayMgrAttr,&feature) == noErr)
  311.         gHasDisplayManager = ((feature & (1 << gestaltDisplayMgrPresent)) != 0);
  312.  
  313. #if    qAOCEAware    
  314.     //    Check for and initialize AOCE Standard Mail package if it exists
  315.     if ((Gestalt(gestaltSMPMailerVersion,&feature) == noErr) && (feature != 0))
  316.         {
  317. #ifdef    powerc
  318.         if ((Ptr) SMPInitMailer != kUnresolvedSymbolAddress)
  319.             gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  320. #else
  321.         gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  322. #endif
  323.         }
  324. #endif
  325.  
  326.     //    Install our AppleEvent Handlers
  327.     InstallAppleEventHandlers();
  328.  
  329.     //    Setup desktop rectangle for dragging windows around            
  330.     GetWMgrPort(&gWindowManagerPort);
  331.     gDeskRectangle = (**GetGrayRgn()).rgnBBox;
  332.  
  333.     //    Get the default menubar
  334.     SetMenuBar(GetNewMBar(rMenuBar));
  335.     AppendResMenu(GetMenuHandle(mApple),'DRVR');
  336.  
  337.     // Add fonts to the font menu if it installed
  338.     if (GetMenuHandle(mFont))
  339.         AppendResMenu(GetMenuHandle(mFont),'FONT');
  340.     
  341.     if (SetupApplication() == noErr)
  342.         {
  343.         delete    splashWindow;    //    get rid of the splash screen
  344.         
  345.         if (!MPLibraryIsLoaded())     { //Don't allow MP tasks
  346.             DisableItem(GetMenuHandle(257),7);
  347.             gHasMPLib = false;
  348.         } else {
  349.         
  350.         }
  351.         MainEventLoop();
  352.         TearDownApplication();
  353.         }
  354.  
  355. #if    qInlineInputAware
  356.     if (gHasTextServices)
  357.         (void) CloseTSMAwareApplication();
  358. #endif
  359.         
  360. #if    qUseQuickDrawGX
  361.     //    Tear down QuickDrawGX
  362.     if (gHasQuickDrawGX && gQuickDrawGXClient)
  363.         {
  364.         DisposeCommonColors();
  365.         GXExitPrinting();        // Close the new printing mgr. 
  366.         GXExitGraphics();        // Deallocate all of the default structures
  367.         GXDisposeGraphicsClient(gQuickDrawGXClient);    
  368.         }
  369. #endif
  370.     }
  371.  
  372. void
  373. MainEventLoop(void)
  374.     {
  375.     EventRecord        anEvent;
  376.     unsigned long    nextTimeToCheckForEvents = 0;
  377.     
  378.     while (!gDone)
  379.         {
  380.         if (gMenuBarNeedsUpdate)
  381.             {
  382.             gMenuBarNeedsUpdate = false;
  383.             DrawMenuBar();
  384.             }
  385.  
  386.         if (gHasThreadManager)
  387.             YieldToAnyThread();
  388.  
  389.         if ((gRunQuantum == 0) ||
  390.             (TickCount() > nextTimeToCheckForEvents))
  391.             {
  392.             nextTimeToCheckForEvents = TickCount() + gRunQuantum;
  393.             
  394.             (void) WaitNextEvent(everyEvent,&anEvent,gSleepQuantum,gMouseRegion);
  395.                         
  396. #if    qInlineInputAware
  397.             if (gHasTextServices && TSMEventWrapperForKotoeri(&anEvent))
  398.                 {
  399.                 }
  400.             else
  401. #endif
  402.                 HandleEvent(&anEvent);
  403.             }
  404.         }
  405.     }
  406.  
  407. #if    qInlineInputAware
  408.  
  409. Boolean
  410. TSMEventWrapperForKotoeri(EventRecord *anEvent)
  411.     {
  412.     short        oldFont;
  413.     ScriptCode    keyboardScript;
  414.     Boolean        didTSMHandleTheEvent = false;
  415.  
  416.     //    This snippet of code is from TE 27: Inline Input & TextEdit
  417.     //    and is related to working around a bug in Kotoeri, one of the
  418.     //    Japanese Input methods when operating in a mixed script
  419.     //    environment (e.g., Japanese Language Kit)
  420.     
  421.     // make sure we have a port and it's not the Window Manager port
  422.     if (qd.thePort != nil)
  423.         {
  424.         oldFont            = qd.thePort->txFont;
  425.         keyboardScript    = GetScriptManagerVariable(smKeyScript);
  426.  
  427.         if (FontToScript(oldFont) != keyboardScript)
  428.             TextFont(GetScriptVariable(keyboardScript, smScriptAppFond));
  429.         }
  430.  
  431.     didTSMHandleTheEvent = TSMEvent(anEvent);
  432.     
  433.     TextFont(oldFont);        //    restore the font, even though the sample code didn’t
  434.  
  435.     return didTSMHandleTheEvent;
  436.     }
  437.  
  438. #endif    
  439.  
  440. void
  441. HandleEvent(EventRecord *anEvent)
  442.     {
  443.     TWindow    * wobj;
  444.     
  445.     if (anEvent->what != updateEvt)
  446.         wobj = GetWindowObject(Front_NonFloatingWindow());
  447.     else
  448.         wobj = GetWindowObject((WindowPtr) anEvent->message);
  449.  
  450.     if (wobj != nil)
  451. #if    qInlineInputAware
  452.         // give text services a chance to set the cursor shape
  453.         if (gHasTextServices && SetTSMCursor(anEvent->where))
  454.             ;    // do nothing, TSM did it for me
  455.         else    
  456. #endif
  457.             wobj->AdjustCursor(anEvent);
  458.     
  459.     if ((wobj != nil) && wobj->EventFilter(anEvent))
  460.         return;
  461.         
  462.     else switch (anEvent->what)
  463.         {
  464.         case    nullEvent:
  465.             WindowPtr aWindow = LMGetWindowList();
  466.             
  467.             while ( aWindow )
  468.             {
  469.                 wobj = GetWindowObject((WindowPtr) aWindow);
  470.                 if (wobj != nil)
  471.                     wobj->Idle(anEvent);
  472.                 aWindow = (WindowPtr)((WindowPeek)aWindow)->nextWindow;
  473.             }
  474.             break;
  475.             
  476.         case    mouseDown:
  477.             HandleMouseDown(wobj,anEvent);
  478.             break;
  479.         
  480.         case    keyDown:
  481.         case    autoKey:
  482.             if (anEvent->modifiers & cmdKey)
  483.                 {
  484.                 long    menuResult = MenuKey((short) anEvent->message & charCodeMask);
  485. #if    qInlineInputAware
  486.                 if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  487. #endif
  488.                     HandleMenu(wobj,menuResult);
  489.                 HiliteMenu(0);
  490.                 }
  491.             else if (wobj != nil)
  492.                 wobj->KeyDown(anEvent);
  493.             break;
  494.             
  495.         case    updateEvt:
  496.             {
  497.             GrafPtr        oldPort;
  498.             WindowPtr    aWindow = (WindowPtr) anEvent->message;    
  499.                 
  500.             GetPort(&oldPort);
  501.             SetPort(aWindow);
  502.             BeginUpdate(aWindow);
  503.             if (wobj != nil)
  504.                 wobj->Draw();
  505.             EndUpdate(aWindow);
  506.             SetPort(oldPort);
  507.             }
  508.             break;
  509.             
  510.         case diskEvt:
  511.             if (anEvent->message >> 16)
  512.                 {
  513.                 static    Point    where = {50,50};
  514.                 (void) DIBadMount(where,anEvent->message);
  515.                 }
  516.             break;
  517.                 
  518.         case    osEvt:
  519.             switch ((anEvent->message & osEvtMessageMask) >> 24)
  520.                 {
  521.                 case    mouseMovedMessage:
  522.                     break;
  523.                     
  524.                 case    suspendResumeMessage:                    
  525.  
  526.                     SuspendResumeWindows((anEvent->message & resumeFlag) != 0);
  527.  
  528.                     if (anEvent->message & resumeFlag)
  529.                         {
  530.                         if (anEvent->message & convertClipboardFlag)
  531.                             ReadLocalClipboardFromScrap();
  532.  
  533.                         gRunQuantum = gForegroundRunQuantum;
  534.                         gSleepQuantum = gForegroundSleepQuantum;
  535.                         }
  536.                     else
  537.                         {
  538.                         if (anEvent->message & convertClipboardFlag)
  539.                             WriteLocalClipboardToScrap();
  540.                         gRunQuantum = gBackgroundRunQuantum;
  541.                         gSleepQuantum = gBackgroundSleepQuantum;
  542.                         }
  543.  
  544.                     break;
  545.                 }
  546.             break;
  547.         
  548.         case    kHighLevelEvent:
  549.             (void) AEProcessAppleEvent(anEvent);
  550.             break;
  551.             
  552.         default:
  553.             break;
  554.         }
  555.     }
  556.  
  557. void
  558. HandleMouseDown(TWindow * topWindowObj,EventRecord *anEvent)
  559.     {
  560.     WindowPtr    aWindow;
  561.     TWindow        *wobj;
  562.     short        partCode;
  563.  
  564.     partCode = FindWindow(anEvent->where,&aWindow);
  565.     wobj = GetWindowObject(aWindow);
  566.     switch(partCode)
  567.         {
  568.         case    inMenuBar:
  569.             long    menuResult = MenuSelect(anEvent->where);
  570. #if    qInlineInputAware
  571.             if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  572. #endif
  573.                 HandleMenu(topWindowObj,menuResult);
  574.             HiliteMenu(0);
  575.             break;
  576.             
  577.         case    inSysWindow:
  578.             SystemClick(anEvent,aWindow);
  579.             break;
  580.             
  581.         case    inContent:
  582.             if (wobj)
  583.                 {
  584.                 GrafPtr    oldPort;
  585.                 
  586.                 GetPort(&oldPort);
  587.                 SetPort(aWindow);
  588.                 GlobalToLocal(&anEvent->where);
  589.                 wobj->Click(anEvent);
  590.                 SetPort(aWindow);
  591.                 }
  592.             break;
  593.             
  594.         case    inDrag:
  595.             if (wobj)
  596.                 wobj->Drag(anEvent->where);
  597.             break;
  598.             
  599.         case    inGrow:
  600.             if (wobj)
  601.                 wobj->Grow(anEvent->where);
  602.             break;
  603.             
  604.         case    inGoAway:
  605.             if (TrackGoAway(aWindow,anEvent->where))
  606.                 HandleClose(aWindow);
  607.             break;
  608.  
  609.         case    inZoomIn:
  610.         case    inZoomOut:
  611.             if (TrackBox(aWindow,anEvent->where,partCode) && (wobj))
  612.                 wobj->Zoom(partCode);
  613.             break;
  614.             
  615.         default:
  616.             break;
  617.         }
  618.     }
  619.     
  620.  
  621. void
  622. HandleClose(WindowPtr aWindow)
  623.     {
  624.     short    windowKind;
  625.     TWindow    *wobj;
  626.     
  627.     if (aWindow)
  628.         {
  629.         windowKind = ((WindowPeek) aWindow)->windowKind;
  630.         if (windowKind < 0)
  631.             {
  632.             CloseDeskAcc(((WindowPeek)aWindow)->windowKind);
  633.             }
  634.         else if ( ((wobj = GetWindowObject(aWindow)) != nil) &&
  635.                     wobj->CanClose() &&
  636.                     wobj->Close() &&
  637.                     wobj->DeleteAfterClose())
  638.             {
  639.             delete wobj;
  640.             }
  641.         }
  642.     }
  643.